﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using QuickGraph;
using GraphSharp;
using GraphSharp.Controls;
using System.IO;
using PI_CS_Library.PicsNetwork_Information_Model;
using PI_CS_Library.Virtual_Network_Information_Model;
using TransportLayer.Manager;
using PI_CS_Library;

namespace PI_CS_GUI
{
    public partial class NetworkViewer : UserControl
    {
        private Topology _network;
        private Topology _vnetwork;

        VertexControl vs;
        EdgeControl ec;
        ImageBrush nodeBrush;
        GUIDelegate _gui;

        int _currId;

        private PicsNetwork _picsNetwork;
        private Engine _managerEngine;
        Dictionary<int, VirtualNetworkOperatorInfo> _VNoperators;

        public NetworkViewer()
        {
            InitializeComponent();
            nodeBrush = new ImageBrush();
            
            try
            {
                nodeBrush.ImageSource = new BitmapImage(new Uri(@"node.png", UriKind.Relative));
            }
            catch (System.NotSupportedException)
            {

            }

        }

        public void Refresh(PicsNetwork _network)
        {
            this._network = new Topology();
            _picsNetwork = _network;
            MapPhysicalNetworkInformation(_network);
            this.graphLayout.Graph = this._network;
            this.DataContext = this._network;
            PrintTopology(this._network);
            _currId = 0;
        }

        public void Refresh(VirtualNetwork _vnetwork)
        {
            this._vnetwork = new Topology();
            MapVirtualNetworkInformation(_vnetwork);
            this.graphLayout.Graph = this._vnetwork;
            this.DataContext = this._vnetwork;
            PrintTopology(this._vnetwork);
            _currId = _vnetwork.Id.Number;
        }

        public void Refresh()
        {
            PrintTopology(this.graphLayout.Graph);
        }

        public void ShowVirtualLink(Topology.Link _vLink)
        {
            this.graphLayout.Graph = this._network;
            this.DataContext = this._network;
            PrintTopology(_vLink, this._network);
            _gui(null, new GUIArgs("showPhysicalTopology"));
            _currId = 0;
        }

        public void ShowVirtualLink(int _id)
        {
            this.graphLayout.Graph = this._network;
            this.DataContext = this._network;
            PrintTopology(VNetwork._edges[_id], this._network);
            _gui(null, new GUIArgs("showPhysicalTopology"));
            _currId = 0;
        }

        private void MapVirtualNetworkInformation(VirtualNetwork _network)
        {
            foreach (PI_CS_Library.Virtual_Network_Information_Model.Matrix _node in _network.MatrixList.Values)
            {
                Topology.Node _newNode = new Topology.Node(_node);
                _vnetwork.AddVertex(_newNode);
            }

            foreach (Link _link in _network.LinkList.Values)
            {
                Topology.Node _source = _vnetwork._nodes[_link.SrcMatrix.Id.Number];
                Topology.Node _sink = _vnetwork._nodes[_link.SinkMatrix.Id.Number];

                Topology.Link _newLink = new Topology.Link(_source, _sink, _link.Parameters.Capacity, _link.Id.Number);
                _vnetwork.AddEdge(_newLink);
            }
        }

        private void MapPhysicalNetworkInformation(PicsNetwork _network)
        {
            foreach (PicsMatrix _node in _network.MatrixResourceList.Values)
            {
                Topology.Node _newNode = new Topology.Node(_node);
                this._network.AddVertex(_newNode);
            }

            foreach (PicsLink _link in _network.LinkResourceList.Values)
            {
                Topology.Node _source = this._network._nodes[_link.SrcMatrix.Id.Number];
                Topology.Node _sink = this._network._nodes[_link.SinkMatrix.Id.Number];

                Topology.Link _newLink = new Topology.Link(_source, _sink, _link.Parameters.Capacity, _link.Id.Number);
                this._network.AddEdge(_newLink);
            }
        }

        private void v_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            VertexControl vs = (VertexControl)(sender);
            
            MatrixPanelGUI _panel = new MatrixPanelGUI(_picsNetwork, _managerEngine, _gui, VNOperators);
            _panel.GetMatrixDetails((Topology.Node)(vs.Vertex));

            _panel.Show();
        }

        private void e_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            EdgeControl es = (EdgeControl)(sender);
            Topology.Link l = (Topology.Link)(es.Edge);

            if (_currId == 0)
            {
                PhysicalLinkGUI _panel = new PhysicalLinkGUI(l.Id, _picsNetwork, _gui, VNOperators);
                _panel.ShowDialog();
            }
            else
            {
                VirtualLinkGUI _panel = new VirtualLinkGUI(l.Source.Id, l.Target.Id, _currId, _picsNetwork, _gui);
                _panel.ShowDialog();
            }
            //ShowVirtualLink((Topology.Link)(es.Edge));
        }

        private void MouseOver(object sender, MouseEventArgs e)
        {
            Control x = (Control)(sender);

            x.Cursor = Cursors.Hand;
        }

        public void PrintTopology(Topology _network)
        {
            foreach (var v in graphLayout.Children)
            {
                if (v is VertexControl)
                    (v as VertexControl).MouseDoubleClick += new MouseButtonEventHandler(v_MouseDoubleClick);
                else if (v is EdgeControl)
                    (v as EdgeControl).MouseDoubleClick += new MouseButtonEventHandler(e_MouseDoubleClick);
               (v as Control).MouseEnter += new MouseEventHandler(MouseOver);
 
            }

            foreach (Topology.Node node in _network.Vertices)
            {
                vs = graphLayout.GetVertexControl(node);
                if (vs != null)
                {
                    GraphCanvas.SetX(vs, node.Position.X);
                    GraphCanvas.SetY(vs, node.Position.Y);
                    vs.Foreground = Brushes.Black;
                    vs.Height = 42;
                    vs.Width = 60;
                    vs.Background = nodeBrush;
                }
            }

            foreach (Topology.Link edge in _network.Edges)
            {
                ec = graphLayout.GetEdgeControl(edge);
                if (ec != null)
                {
                    ec.Foreground = Brushes.Gray;
                }
            }

        }

        public void PrintTopology(Topology.Link _vLink, Topology _network)
        {
            foreach (var v in graphLayout.Children)
            {
                if (v is VertexControl)
                    (v as VertexControl).MouseDoubleClick += new MouseButtonEventHandler(v_MouseDoubleClick);
                else if (v is EdgeControl)
                    (v as EdgeControl).MouseDoubleClick += new MouseButtonEventHandler(e_MouseDoubleClick);
                (v as Control).MouseEnter += new MouseEventHandler(MouseOver);

            }

            foreach (Topology.Node node in _network.Vertices)
            {
                vs = graphLayout.GetVertexControl(node);
                if (vs != null)
                {
                    GraphCanvas.SetX(vs, node.Position.X);
                    GraphCanvas.SetY(vs, node.Position.Y);
                    vs.Foreground = Brushes.Black;
                    vs.Height = 42;
                    vs.Width = 60;
                    vs.Background = nodeBrush;
                }
            }

            List<int> _virtualLinkEdges = new List<int>();
            int _vLinkId = _picsNetwork.LinkMappingList[_vLink.Id];
            PicsVirtualLink _picsVLink = _picsNetwork.VirtualLinkList[_vLinkId];

            foreach (PicsLink l in _picsVLink.PicsLinkList.Values)
            {
                _virtualLinkEdges.Add(l.Id.Number);
                foreach (Topology.Link edge in _network.Edges)
                {
                    if ((edge.Source.Id == l.SinkMatrix.Id.Number) && (edge.Target.Id == l.SrcMatrix.Id.Number))
                    {
                        _virtualLinkEdges.Add(edge.Id);
                    }
                }
            }

            foreach (Topology.Link edge in _network.Edges)
            {
                if (!_virtualLinkEdges.Contains(edge.Id))
                {
                    ec = graphLayout.GetEdgeControl(edge);
                    if (ec != null)
                    {
                        ec.Foreground = Brushes.Gray;
                    }
                }
                else
                {
                    ec = graphLayout.GetEdgeControl(edge);
                    if (ec != null)
                    {
                        ec.Foreground = Brushes.Orange;
                    }
                }
            }

        }

        public Topology Network
        {
            get { return _network; }
            set { _network = value; }
        }

        public Topology VNetwork
        {
            get { return _vnetwork; }
            set { _vnetwork = value; }
        }

        public Dictionary<int, VirtualNetworkOperatorInfo> VNOperators
        {
            get { return _VNoperators; }
            set { _VNoperators = value; }
        }

        public Engine ManagerEngine
        {
            get { return _managerEngine; }
            set { _managerEngine = value; }
        }

        public GUIDelegate GUI
        {
            get { return _gui; }
            set { _gui = value; }
        }

    }

}
